package cc.uncarbon.module.custom.service;

import cc.uncarbon.framework.core.constant.HelioConstant;
import cc.uncarbon.framework.core.exception.BusinessException;
import cc.uncarbon.framework.core.page.PageParam;
import com.yanrumiao.entity.PageResult;
import cc.uncarbon.module.custom.entity.UserEntity;
import cc.uncarbon.module.custom.mapper.UserMapper;
import cc.uncarbon.module.custom.model.request.AdminUserInsertOrUpdateDTO;
import cc.uncarbon.module.custom.model.request.AdminUserListDTO;
import cc.uncarbon.module.custom.model.response.UserBO;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;


/**
 * 用户信息
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class UserService {

    private final UserMapper userMapper;


    /**
     * 后台管理-分页列表
     */
    public PageResult<UserBO> adminList(PageParam pageParam, AdminUserListDTO dto) {
        Page<UserEntity> entityPage = userMapper.selectPage(
                new Page<>(pageParam.getPageNum(), pageParam.getPageSize()),
                new QueryWrapper<UserEntity>()
                        .lambda()
                        // 姓名
                        .like(CharSequenceUtil.isNotBlank(dto.getName()), UserEntity::getName, CharSequenceUtil.cleanBlank(dto.getName()))
                        // 昵称
                        .like(CharSequenceUtil.isNotBlank(dto.getNickname()), UserEntity::getNickname, CharSequenceUtil.cleanBlank(dto.getNickname()))
                        // 密码，建议加密存储
                        .like(CharSequenceUtil.isNotBlank(dto.getPassword()), UserEntity::getPassword, CharSequenceUtil.cleanBlank(dto.getPassword()))
                        // 头像URL
                        .like(CharSequenceUtil.isNotBlank(dto.getAvatar()), UserEntity::getAvatar, CharSequenceUtil.cleanBlank(dto.getAvatar()))
                        // 性别,1，男，2，女
                        .eq(ObjectUtil.isNotNull(dto.getSex()), UserEntity::getSex, dto.getSex())
                        // 微信唯一标识
                        .like(CharSequenceUtil.isNotBlank(dto.getWxUnionid()), UserEntity::getWxUnionid, CharSequenceUtil.cleanBlank(dto.getWxUnionid()))
                        // 微信昵称
                        .like(CharSequenceUtil.isNotBlank(dto.getWxName()), UserEntity::getWxName, CharSequenceUtil.cleanBlank(dto.getWxName()))
                        // 手机号
                        .like(CharSequenceUtil.isNotBlank(dto.getPhone()), UserEntity::getPhone, CharSequenceUtil.cleanBlank(dto.getPhone()))
                        // 生日
                        .eq(ObjectUtil.isNotNull(dto.getBirthday()), UserEntity::getBirthday, dto.getBirthday())
                        // 消费金额
                        .eq(ObjectUtil.isNotNull(dto.getConsumptionAmount()), UserEntity::getConsumptionAmount, dto.getConsumptionAmount())
                        // 进店次数
                        .eq(ObjectUtil.isNotNull(dto.getServiceCount()), UserEntity::getServiceCount, dto.getServiceCount())
                        // 访问次数
                        .eq(ObjectUtil.isNotNull(dto.getVisitCount()), UserEntity::getVisitCount, dto.getVisitCount())
                        // 时间区间
                        .between(ObjectUtil.isNotNull(dto.getBeginAt()) && ObjectUtil.isNotNull(dto.getEndAt()), UserEntity::getCreatedAt, dto.getBeginAt(), dto.getEndAt())
                        // 排序
                        .orderByDesc(UserEntity::getCreatedAt)
        );

        return this.entityPage2BOPage(entityPage);
    }

    /**
     * 根据 ID 取详情
     *
     * @param id 主键ID
     * @return null or BO
     */
    public UserBO getOneById(Long id) {
        return this.getOneById(id, false);
    }

    /**
     * 根据 ID 取详情
     *
     * @param id 主键ID
     * @param throwIfInvalidId 是否在 ID 无效时抛出异常
     * @return null or BO
     */
    public UserBO getOneById(Long id, boolean throwIfInvalidId) throws BusinessException {
        UserEntity entity = userMapper.selectById(id);
        if (throwIfInvalidId && entity == null) {
            throw new BusinessException(400, "无效用户信息ID");
        }

        return this.entity2BO(entity);
    }

    /**
     * 后台管理-新增
     */
    @Transactional(rollbackFor = Exception.class)
    public Long adminInsert(AdminUserInsertOrUpdateDTO dto) {
        log.info("[后台管理-用户信息-新增] >> DTO={}", dto);
        this.checkExistence(dto);

        dto.setId(null);
        UserEntity entity = new UserEntity();
        BeanUtil.copyProperties(dto, entity);

        userMapper.insert(entity);

        return entity.getId();
    }

    /**
     * 后台管理-编辑
     */
    @Transactional(rollbackFor = Exception.class)
    public void adminUpdate(AdminUserInsertOrUpdateDTO dto) {
        log.info("[后台管理-用户信息-编辑] >> DTO={}", dto);
        this.checkExistence(dto);

        UserEntity entity = new UserEntity();
        BeanUtil.copyProperties(dto, entity);

        userMapper.updateById(entity);
    }

    /**
     * 后台管理-删除
     */
    @Transactional(rollbackFor = Exception.class)
    public void adminDelete(Collection<Long> ids) {
        log.info("[后台管理-用户信息-删除] >> ids={}", ids);
        userMapper.deleteBatchIds(ids);
    }


    /*
    ----------------------------------------------------------------
                        私有方法 private methods
    ----------------------------------------------------------------
     */

    /**
     * 实体转 BO
     *
     * @param entity 实体
     * @return BO
     */
    private UserBO entity2BO(UserEntity entity) {
        if (entity == null) {
            return null;
        }

        UserBO bo = new UserBO();
        BeanUtil.copyProperties(entity, bo);

        // 可以在此处为BO填充字段

        return bo;
    }

    /**
     * 实体 List 转 BO List
     *
     * @param entityList 实体 List
     * @return BO List
     */
    private List<UserBO> entityList2BOs(List<UserEntity> entityList) {
        if (CollUtil.isEmpty(entityList)) {
            return Collections.emptyList();
        }

        // 深拷贝
        List<UserBO> ret = new ArrayList<>(entityList.size());
        entityList.forEach(
            entity -> ret.add(this.entity2BO(entity))
        );

        return ret;
    }

    /**
     * 实体分页转 BO 分页
     *
     * @param entityPage 实体分页
     * @return BO 分页
     */
    private PageResult<UserBO> entityPage2BOPage(Page<UserEntity> entityPage) {
        return new PageResult<UserBO>()
            .setCurrent((int) entityPage.getCurrent())
            .setSize((int) entityPage.getSize())
            .setTotal((int) entityPage.getTotal())
            .setRecords(this.entityList2BOs(entityPage.getRecords()));
    }

    /**
     * 检查是否已存在同名数据
     *
     * @param dto DTO
     */
    private void checkExistence(AdminUserInsertOrUpdateDTO dto) {
        /*
        可以根据自己业务需要，解禁这段代码，修改判断条件和文案

        UserEntity existingEntity = userMapper.selectOne(
                new QueryWrapper<UserEntity>()
                        .lambda()
                        .select(UserEntity::getId)
                        .eq(UserEntity::getTitle, dto.getTitle())
                        .last(HelioConstant.CRUD.SQL_LIMIT_1)
        );

        if (existingEntity != null && !existingEntity.getId().equals(dto.getId())) {
            throw new BusinessException(400, "已存在相同用户信息，请重新输入");
        }
        */
    }

}
